﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NetLib.web;
using System.Collections;
using HAP = HtmlAgilityPack;
using StockCommon;
using System.Threading;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using Utilities;

namespace StockImport.dataimport.basicdata
{
    public class MopsBasicDataUpdater
    {

        String url = "http://mops.twse.com.tw/mops/web/ajax_t51sb01";
        String host = "mops.twse.com.tw";

        protected bool createNewCompanyInfo(Dictionary<String, String> data)
        {
            CompanyInfo compInfo = new CompanyInfo();
            StockDataClassesDataContext context = LinqAgent.getContext();

            compInfo.公司代號 = data["公司代號"];
            compInfo.公司名稱 = data["公司名稱"];
            compInfo.住址 = data["住址"];
            compInfo.營利事業統一編號 = data["營利事業統一編號"];
            compInfo.董事長 = data["董事長"];
            compInfo.總經理 = data["總經理"];
            compInfo.發言人 = data["發言人"];
            compInfo.發言人職稱 = data["發言人職稱"];
            compInfo.代理發言人 = data["代理發言人"];
            compInfo.總機電話 = data["總機電話"];
            compInfo.股票過戶機構 = data["股票過戶機構"];
            compInfo.過戶電話 = data["過戶電話"];
            compInfo.過戶地址 = data["過戶地址"];
            compInfo.簽證會計師事務所 = data["簽證會計師事務所"];
            compInfo.簽證會計師1 = data["簽證會計師1"];
            compInfo.簽證會計師2 = data["簽證會計師2"];
            compInfo.英文簡稱 = data["英文簡稱"];
            compInfo.英文通訊地址 = data["英文通訊地址"];
            compInfo.傳真機號碼 = data["傳真機號碼"];
            compInfo.電子郵件信箱 = data["電子郵件信箱"];
            compInfo.網址 = data["網址"];


            compInfo.成立日期 = DateUtils.parseROCDate(data["成立日期"]);
            String update = "";
            if (data.ContainsKey("上市日期"))
                update = data["上市日期"];

            if (data.ContainsKey("上櫃日期"))
                update = data["上櫃日期"];

            compInfo.上市日期 = DateUtils.parseROCDate(update);
            compInfo.實收資本額 = decimal.Parse(data["實收資本額(元)"].Trim());
            compInfo.id = NewGUID.create("stck");
            compInfo.Alive = true;
            compInfo.Deleted = false;
            compInfo.marketType = data["market"];
            compInfo.產業類別 = data["gallery"];
            compInfo.LastModifiedDate = DateTime.Now;
            context.CompanyInfos.InsertOnSubmit(compInfo);
            return true;
        }
        protected bool checkUpdateCompanyInfo(CompanyInfo compInfo, Dictionary<String, String> data)
        {
            CompanyInfo_updatelog updateLog = new CompanyInfo_updatelog();
            bool changed = false;

            if (compInfo.住址.Equals(data["住址"]) == false)
            {
                updateLog.住址 = compInfo.住址;
                compInfo.住址 = data["住址"];
                changed = true;
            }

            if (compInfo.董事長.Equals(data["董事長"]) == false)
            {
                compInfo.董事長 = data["董事長"];
                updateLog.董事長 = compInfo.董事長;
                changed = true;
            }

            if (compInfo.總經理.Equals(data["總經理"]) == false)
            {
                compInfo.總經理 = data["總經理"];
                updateLog.總經理 = compInfo.總經理;
                changed = true;
            }
            if (compInfo.發言人.Equals(data["發言人"]) == false)
            {
                compInfo.發言人 = data["發言人"];
                updateLog.發言人 = compInfo.發言人;
                changed = true;
            }

            if (compInfo.發言人職稱.Equals(data["發言人職稱"]) == false)
            {
                compInfo.發言人職稱 = data["發言人職稱"];
                updateLog.發言人職稱 = compInfo.發言人職稱;
                changed = true;
            }
            if (compInfo.代理發言人.Equals(data["代理發言人"]) == false)
            {
                compInfo.代理發言人 = data["代理發言人"];
                updateLog.代理發言人 = compInfo.代理發言人;
                changed = true;
            }
            if (compInfo.股票過戶機構.Equals(data["股票過戶機構"]) == false)
            {
                compInfo.股票過戶機構 = data["股票過戶機構"];
                updateLog.股票過戶機構 = compInfo.股票過戶機構;
                changed = true;
            }

            if (compInfo.簽證會計師事務所.Equals(data["簽證會計師事務所"]) == false)
            {
                compInfo.簽證會計師事務所 = data["簽證會計師事務所"];
                updateLog.簽證會計師事務所 = compInfo.簽證會計師事務所;
                changed = true;
            }
            if (compInfo.簽證會計師1.Equals(data["簽證會計師1"]) == false)
            {
                compInfo.簽證會計師1 = data["簽證會計師1"];
                updateLog.簽證會計師1 = compInfo.簽證會計師1;
                changed = true;
            }
            if (compInfo.簽證會計師2.Equals(data["簽證會計師2"]) == false)
            {
                compInfo.簽證會計師2 = data["簽證會計師2"];
                updateLog.簽證會計師2 = compInfo.簽證會計師2;
                changed = true;
            }

            decimal newv=decimal.Parse(data["實收資本額(元)"].Trim());

            if (compInfo.實收資本額.Equals(newv) == false)
            {
                updateLog.實收資本額 = compInfo.實收資本額;
                compInfo.實收資本額 = newv;
                changed = true;
            }
            if (changed)
            {
                StockDataClassesDataContext context = LinqAgent.getContext();
                updateLog.companyid = compInfo.id;
                updateLog.公司代號 = compInfo.公司代號;
                updateLog.公司名稱 = compInfo.公司名稱;
                updateLog.logDate = DateTime.Now;
                context.CompanyInfo_updatelogs.InsertOnSubmit(updateLog);
                return true;
            }
            return false;
        }
        protected void updateToCompanyInfo(List<Dictionary<String, String>> rows)
        {
            StockDataClassesDataContext context = LinqAgent.getContext();
            Dictionary<String, CompanyInfo> oldDatas = (from ci in context.CompanyInfos select ci).ToDictionary(x => x.公司代號);
            bool haschanged = false;
            foreach (Dictionary<String, String> row in rows)
            {
                String code = row["公司代號"];
                bool r;
                if (oldDatas.ContainsKey(code))
                    r = checkUpdateCompanyInfo(oldDatas[code], row);
                else
                {
                    r = createNewCompanyInfo(row);
                }
                haschanged |= r;
            }
            if(haschanged)
            context.SubmitChanges();
        }
        //--------------------------------------
        protected void update_internal()
        {
            List<Dictionary<String, String>> newBasicDatas = getBasicDataOnSite();
            updateToCompanyInfo(newBasicDatas);
        }

        List<Dictionary<String, String>> getBasicDataOnSite()
        {
            String fileName = @"o:\data.bin";
            List<Dictionary<String, String>> allRows = new List<Dictionary<string, string>>();

            if (File.Exists(fileName))
            {
                DateTime creationTime = File.GetCreationTime(fileName);
                TimeSpan ts = DateTime.Now.Subtract(creationTime);
                if (ts.Days > 1)
                    File.Delete(fileName);
            }


            if (File.Exists(fileName) == false)
            {
                List<Dictionary<String, String>> tseStock = fetchMarket("tse");
                List<Dictionary<String, String>> otcStock = fetchMarket("otc");
                allRows.AddRange(tseStock);
                allRows.AddRange(otcStock);
                SerializeUtils.SaveToFile(fileName, allRows);
            }
            else
            {
                allRows = (List<Dictionary<String, String>>)SerializeUtils.LoadFromFile(fileName);
            }
            return allRows;
        }


        public void Update()
        {
            //------------>
            update_internal();


        }


        protected List<Dictionary<String, String>> fetchMarket(String market)
        {
            List<Dictionary<String, String>> allrows = new List<Dictionary<string, string>>();

            Dictionary<String, String> gallerys = getSelectCodeNames(market);
            if (gallerys != null)
            {
                Hashtable ps = new Hashtable();
                ps.Add("encodeURIComponent", "1");
                ps.Add("step", "1");
                ps.Add("firstin", "1");
                if ("tse".Equals(market))
                    ps.Add("TYPEK", "sii");
                else
                    ps.Add("TYPEK", "otc");
                ps.Add("code", "");

                foreach (String k in gallerys.Keys)
                {
                    ps["code"] = k;
                    String content = HttpPost.Request(url, ps, Encoding.UTF8, null);
                    if (content.StartsWith("Error"))
                        continue;
                    List<Dictionary<String, String>> rows = fetchRowFromHtml(content);

                    if (rows.Count == 0)
                    {
                        /*
                        Thread.Sleep(1000);
                        content = HttpPost.Request(url, ps, Encoding.UTF8, null);
                        if (content.StartsWith("Error"))
                            continue;
                        rows = fetchRowFromHtml(content);*/
                        continue;
                    }

                    String galleryName = gallerys[k];
                    foreach (Dictionary<String, String> row in rows)
                    {
                        row.Add("market", market);
                        row.Add("gallery", galleryName);
                    }
                    allrows.AddRange(rows);
                    rows.Clear();
                }

            }
            return allrows;

        }

        protected List<Dictionary<String, String>> fetchRowFromHtml(String content)
        {
            HAP.HtmlDocument doc = new HAP.HtmlDocument();
            doc.LoadHtml(content);

            List<Dictionary<String, String>> rows = new List<Dictionary<string, string>>();
            HAP.HtmlNodeCollection nodes = doc.DocumentNode.SelectNodes("//tr");

            if (nodes == null)
                return rows;
            Dictionary<int, String> columnHeader = new Dictionary<int, string>();
            //找到header
            foreach (HAP.HtmlNode row in nodes)
            {
                if (row.ChildNodes.Count > 20)
                {
                    int sz = row.ChildNodes.Count;
                    for (int i = 0; i < sz; i++)
                    {
                        String h = row.ChildNodes[i].InnerText.Trim();
                        columnHeader.Add(i, h);
                    }
                    break;
                }
            }
            foreach (HAP.HtmlNode row in nodes)
            {
                if (row.ChildNodes.Count < 20)
                    continue;
                if (row.ChildNodes[1].InnerText.Contains("公司名稱"))
                    continue;
                int sz = row.ChildNodes.Count;
                Dictionary<String, String> rowdata = new Dictionary<string, string>();
                for (int i = 0; i < sz; i++)
                {
                    String h = row.ChildNodes[i].InnerText.Trim();
                    h = h.Replace("&nbsp;", "").Trim();
                    String k = columnHeader[i];
                    rowdata.Add(k, h);
                }
                rows.Add(rowdata);
            }
            return rows;
        }


        protected Dictionary<String, String> getSelectCodeNames(String type)
        {

            Hashtable headerSet = new Hashtable();
            headerSet.Add("Referer", url);
            headerSet.Add("User-Agent", "	Mozilla/5.0 (Windows NT 6.1; WOW64; rv:15.0) Gecko/20100101 Firefox/15.0.1");
            headerSet.Add("Host", host);
            headerSet.Add("Accept-Language", "zh-tw,en-us;q=0.7,en;q=0.3");
            headerSet.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");

            Hashtable ps = new Hashtable();
            ps.Add("encodeURIComponent", "1");
            ps.Add("step", "2");
            ps.Add("firstin", "1");
            if ("tse".Equals(type))
                ps.Add("TYPEK", "sii");
            else
                ps.Add("TYPEK", "otc");
            ps.Add("code", "");
            String content = HttpPost.Request(url, ps, Encoding.UTF8, headerSet);
            if (content.StartsWith("Error"))
                return null;

            //select name="code"
            HAP.HtmlDocument doc = new HAP.HtmlDocument();
            doc.LoadHtml(content);
            HAP.HtmlNode node = doc.DocumentNode.SelectSingleNode("//select[@name='code']");
            if (node == null)
                return null;

            Dictionary<String, String> codeNames = new Dictionary<String, String>();

            HAP.HtmlNodeCollection nodes = node.SelectNodes(node.XPath + "/option");

            foreach (HAP.HtmlNode n in nodes)
            {
                String v = n.GetAttributeValue("value", "");
                if (String.IsNullOrWhiteSpace(v))
                    continue;
                String name = n.NextSibling.InnerText;
                codeNames.Add(v, name.Trim());
            }
            return codeNames;
        }

    }
}
